
# these are the regular paths and definitions
INCLUDE_DIR := include
SRC_DIR := src
TGT_DIR := tgt
TEST_DIR := .

C_DIR := c
SCM_DIR := scheme
ML_DIR := .
OBJ_DIR := obj

# GENERAL
DEFAULT_EXECUTABLE ?= $(TGT_DIR)/schemeprog
GENERATED_CODE_OBJ := $(TGT_DIR)/$(OBJ_DIR)/code.o

# ML
ML_RUNNER := $(TEST_DIR)/mlrunner.sml
ML_COMPILER := $(SRC_DIR)/$(ML_DIR)/compiler.sml
ML_WORKSPACE := $(ML_RUNNER) $(ML_COMPILER)

# SCHEME
SUPPORT_CODE_SCM := $(SRC_DIR)/$(SCM_DIR)/support-code.scm

# C
MODULES := env machine scheme schemeobject toplevel
STD_HEADERS := debug base
GENERATED_CODE_C := $(SRC_DIR)/$(C_DIR)/code.c
SUPPORT_CODE_C := $(SRC_DIR)/$(C_DIR)/supportcode.c
TMP_SUPPORT_CODE  := $(addsuffix ~,$(SUPPORT_CODE_C))
RUNTIME_CODE_C :=  $(SRC_DIR)/$(C_DIR)/runtime.c
GENERATED_CODE_C_PREREQ = $(SUPPORT_CODE_C) $(RUNTIME_CODE_C)
OBJECTS := $(addprefix $(TGT_DIR)/$(OBJ_DIR)/,$(addsuffix .o, $(MODULES) main))
SOURCES := $(addprefix $(SRC_DIR)/$(C_DIR)/,$(addsuffix .c, $(MODULES) main $(GENERATED_CODE_C))) $(SUPPORT_CODE_C) $(RUNTIME_CODE_C)
HEADERS := $(addprefix $(SRC_DIR)/$(C_DIR)/,$(addsuffix .h, schemebase $(MODULES))) # for convenience, all sources depend on all headers
INCLUDES := $(addprefix $(INCLUDE_DIR)/, $(addsuffix .h, $(STD_HEADERS)))

ML = sml $(ML_RUNNER)
CC = gcc -c -I$(INCLUDE_DIR)
LD = gcc

# utility
# -------

.IGNORE: clean nosupport

all: $(DEFAULT_EXECUTABLE)

supportcode: $(SUPPORT_CODE_C) ;

# support code is not removed, targets which are not in tgt also not removed.
.PHONY: clean
clean:
	-rm -R $(TGT_DIR)
	-rm $(GENERATED_CODE_C)

.PHONY: nosupport
nosupport:
	-rm $(SUPPORT_CODE_C)

# executables
# -----------

$(DEFAULT_EXECUTABLE): $(OBJECTS) $(GENERATED_CODE_OBJ)
	$(LD) -o $@ $^

%: %.c
 
# user has to say which c file is going to be compiled
%: %.c $(GENERATED_CODE_C_PREREQ) $(OBJECTS)
	ln -f $*.c $(GENERATED_CODE_C)
	$(CC) -o $(GENERATED_CODE_OBJ) $(GENERATED_CODE_C)
	$(LD) -o $@ $(OBJECTS) $(GENERATED_CODE_OBJ)

# objects
# -------

$(TGT_DIR)/$(OBJ_DIR)/%.o: $(SRC_DIR)/$(C_DIR)/%.c $(INCLUDES) $(HEADERS)
	-mkdir -p $(TGT_DIR)/$(OBJ_DIR)
	$(CC) -o $@ $(SRC_DIR)/$(C_DIR)/$*.c

$(GENERATED_CODE_OBJ): $(GENERATED_CODE_C) $(GENERATED_C_CODE_PREREQ)
	-mkdir -p $(TGT_DIR)/$(OBJ_DIR)
	$(CC) -o $@ $(GENERATED_CODE_C)

# c source code
# -------------

GENERATED_CODE_HEADER_SIZE_LINES := 11
GENERATED_CODE_FOOTER_SIZE_LINES := 4
# this works by generating regular code and trimming the last 5 lines and the first 11 lines
$(SUPPORT_CODE_C): $(SUPPORT_CODE_SCM)
	$(ML) $^ $(TMP_SUPPORT_CODE)
	cat $(TMP_SUPPORT_CODE) | sed '1,$(GENERATED_CODE_HEADER_SIZE_LINES)d' | sed -n -e :a -e '1,$(GENERATED_CODE_FOOTER_SIZE_LINES)!{P;N;D;};N;ba' > $@

%.c: %.scm $(ML_WORKSPACE)
	$(ML) $*.scm $@

%.c: %.ss $(ML_WORKSPACE)
	$(ML) $*.ss $@

# scheme source code
# ------------------

%.scm:

%.ss:

# ml source code
# --------------

%.sml:


